package slicegen;

import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.util.Comparator;

import javax.vecmath.Point3d;
import javax.vecmath.Vector3d;

public class Triangle implements Comparable
{
	public Triangle(Point3d p1, Point3d p2, Point3d p3)
	{
		this.p1 = p1;
		this.p2 = p2;
		this.p3 = p3;
		
		
		/*
		 * P2------->P3
		 *   /\		/
		 * 	   \  \/
		 * 		P1
		 */		
		
		minZ = Math.min(p1.z, Math.min(p2.z, p3.z));
		maxZ = Math.max(p1.z, Math.max(p2.z, p3.z));
	}
	
	@Override
	public boolean equals(Object obj) {
		if (obj instanceof Triangle)
		{
			Triangle t = (Triangle) obj;
			return (p1.equals(t.p1) && p2.equals(t.p2) && p3.equals(t.p3));
		}
		
		return false;
	}
	
	public int compareTo(Object arg0)
	{
		if (arg0 instanceof Triangle)
			return (int) Math.signum(minZ - ((Triangle) arg0).minZ);
		else
			return 0;
	}	
	
	/**
	 * 
	 * @param zLevel
	 * @return The line segment on the z-plane that is the intersection with the triangle
	 */
	public Line intersectWithZPlane(double zLevel, boolean zTravelUp)
	{
		Plane zPlane;
		
		//Normal is up
		if (zTravelUp)		
			zPlane = new Plane(new Point3d(0, 0, zLevel), upNormal);
		else
			zPlane = new Plane(new Point3d(0, 0, zLevel), downNormal);	
		
		//Determine which point is on the "wrong" side of the plane		
		double p1Dist = zPlane.distanceToPlane(p1);
		double p2Dist = zPlane.distanceToPlane(p2);
		double p3Dist = zPlane.distanceToPlane(p3);
		
		/*if (Math.abs(p1Dist) < TOL)
		    p1Dist = 0.0;
		if (Math.abs(p2Dist) < TOL)
		    p2Dist = 0.0;
		if (Math.abs(p3Dist) < TOL)
		    p3Dist = 0.0;
	*/
		/*
		 * 	Segments of the triangle that pierce the plane
		 */
		Segment s1, s2;
		
		if (Math.signum(p1Dist) != Math.signum(p2Dist))
		{
			if (Math.signum(p1Dist) != Math.signum(p3Dist))
			{
				//p1 is the odd point
				//p2->p1
				//p3->p1
				s1 = new Segment(p2, p1);
				s2 = new Segment(p3, p1);				
			}
			else
			{
				//p2 is the odd point
				s1 = new Segment(p1, p2);
				s2 = new Segment(p3, p2);
			}
		}
		else
		{
			//p3 is the odd point
			s1 = new Segment(p1, p3);
			s2 = new Segment(p2, p3);			
		}

		Point3d intersection1 = s1.planeIntersect(zPlane);
		Point3d intersection2 = s2.planeIntersect(zPlane);
		
		if (intersection1 == null || intersection2 == null)
		{
		    return null;
		}
		
		Line sliceSegment = new Line(new Point2D.Double(intersection1.x, intersection1.y),
											new Point2D.Double(intersection2.x, intersection2.y));
		
		//System.out.println(sliceSegment.getP1() + " " + sliceSegment.getP2());
		return sliceSegment;
	}
	
	@Override
	public String toString() {
		return p1 + " " + p2 + " " + p3;
	}
	
	class Point3dComparator implements Comparator
	{
		public int compare(Object arg0, Object arg1)
		{   	
			return (int) Math.signum( ((Point3d) arg0).z - ((Point3d) arg1).z);			
		}		
	}
	
	Point3d p1, p2, p3;
	double maxZ, minZ;
	
	private static final double TOL = 1e-4;
	private static Vector3d upNormal = new Vector3d(0, 0, 1);
	private static Vector3d downNormal = new Vector3d(0, 0, -1);
}
